﻿/**
 * BlurZFilter
 *
 * @author		Allen Chou
 * @version		1.0.0 (last update: Dec 10 2008)
 * @link        http://cjcat.blogspot.com
 * @link		http://cjcat2266.deviantart.com
 */

package idv.cjcat.display.zsorter {
	import flash.filters.BlurFilter;
	
	import idv.cjcat.CJMath;
	
	/**
	 * The <code>BlurZFilter</code> class applies a depth-of-field blurring effect.
	 * <p>
	 * Display objects having z-depth between the near and far z planes would not be affected.
	 * The blur amount is interpolated if a display object is beyond the "unaffected range",
	 * for a range of near and far ranges beyond near and far z planes, respectively.
	 * </p>
	 */
	public class BlurZFilter implements IZFilter {
		
		private var _nearZ:Number;  //small
		private var _farZ:Number;  //large
		private var _nearRange:Number;
		private var _farRange:Number;
		
		/**
		 * The maximum amount of blur.
		 */
		public var blur:Number = 10;
		/**
		 * The quality of blur. 1 for the worst quality, 2 for medium quality, and 3 for the best quality.
		 */
		public var quality:int = 1;
		
		/**
		 * Creates a z-filter that applies a depth-of-field blurring effect.
		 * @param	nearZ  The near z plane.
		 * @param	farZ   The far z plane.
		 * @param	range  The range of variation.
		 */
		public function BlurZFilter(nearZ:Number, farZ:Number, range:Number = 50) {
			this.nearZ = nearZ;
			this.farZ = farZ;
			_nearRange = _farRange = range;
		}
		
		private var dz:Number;
		private var filter:BlurFilter;
		public function process(data:ZData):void {
			dz = data.cameraZ;
			filter = new BlurFilter(0, 0, quality);
			
			if (dz > _nearZ && dz < _farZ) return;
			
			if (dz <= _nearZ) {
				filter.blurX = filter.blurY = CJMath.clamp(CJMath.interpolate(_nearZ, 0, _nearZ - _nearRange, blur, dz), 0, blur);
			} else if (dz >= _farZ) {
				filter.blurX = filter.blurY = CJMath.clamp(CJMath.interpolate(_farZ, 0, _farZ + _farRange, blur, dz), 0, blur);
			}
			
			data.obj.filters = data.obj.filters.concat(filter);
		}
		
		/**
		 * The near z plane.
		 */
		public function get nearZ():Number { return _nearZ; }
		public function set nearZ(value:Number):void { _nearZ = CJMath.clamp(value, -Number.MAX_VALUE, _farZ); }
		/**
		 * The near range of variation.
		 */
		public function get nearRange():Number { return _nearRange; }
		public function set nearRange(value:Number):void { _nearRange = CJMath.clamp(value, 0, Number.MAX_VALUE); }
		/**
		 * The far z plane.
		 */
		public function get farZ():Number { return _farZ; }
		public function set farZ(value:Number):void { _farZ = CJMath.clamp(value, _nearZ, Number.MAX_VALUE); }
		/**
		 * The far range of variation.
		 */
		public function get farRange():Number { return _farRange; }
		public function set farRange(value:Number):void { _farRange = CJMath.clamp(value, 0, Number.MAX_VALUE); }
		
	}
}